﻿using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BoringTodo
{
    public enum LogLevel
    {
        Debug,
        Info,
        Warning,
        Error
    }

    public static class Logger
    {
        private static readonly object _lock = new object();
        private static string _logFilePath;
        private static string _logFolder;
        private static LogLevel _minimumLogLevel = LogLevel.Info;
        private static bool _isInitialized = false;
        private static StringBuilder _logBuffer = new StringBuilder(8192); // 预分配更大的缓冲区
        private static Timer _flushTimer;
        private static readonly int _bufferFlushInterval = 5000; // 减少到5秒以提高实时性
        private static ConcurrentQueue<LogEntry> _logQueue = new ConcurrentQueue<LogEntry>(); // 使用线程安全队列
        private static Task _logProcessingTask; // 后台日志处理任务
        private static readonly int MAX_LOG_FILE_SIZE = 10 * 1024 * 1024; // 10MB
        private static readonly int MAX_LOG_FILES = 10;
        private static CancellationTokenSource _logCancellation = new CancellationTokenSource();
        
        struct LogEntry
        {
            public string Message;
            public LogLevel Level;
            public DateTime Timestamp;
            public Exception Exception;
        }
        
        public static LogLevel MinimumLogLevel
        {
            get => _minimumLogLevel;
            set => _minimumLogLevel = value;
        }

        static Logger()
        {
            Initialize();
        }

        public static void Initialize()
        {
            if (_isInitialized)
                return;

            try
            {
                // 创建日志文件路径
                _logFolder = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                    Constants.AppDataFolder,
                    Constants.LogsFolder
                );

                // 确保日志文件夹存在
                if (!Directory.Exists(_logFolder))
                {
                    Directory.CreateDirectory(_logFolder);
                }

                // 以日期命名日志文件
                string logFileName = $"log_{DateTime.Now.ToString("yyyyMMdd")}.txt";
                _logFilePath = Path.Combine(_logFolder, logFileName);

                // 初始化缓冲区刷新计时器
                _flushTimer = new Timer(FlushLogBuffer, null, _bufferFlushInterval, _bufferFlushInterval);

                // 启动日志处理任务
                StartLogProcessingTask();
                
                // 清理旧日志文件
                Task.Run(CleanupOldLogs);
                
                _isInitialized = true;

                // 记录应用程序启动日志
                Log($"应用程序启动，版本：{Constants.AppVersion}", LogLevel.Info);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"初始化日志系统失败: {ex.Message}");
                // 不要在这里调用Log，会导致无限递归
            }
        }

        private static void StartLogProcessingTask()
        {
            _logProcessingTask = Task.Run(async () =>
            {
                while (!_logCancellation.Token.IsCancellationRequested)
                {
                    // 每100毫秒处理一次日志队列
                    await Task.Delay(100, _logCancellation.Token);
                    ProcessLogQueue();
                }
            }, _logCancellation.Token);
        }
        
        private static void ProcessLogQueue()
        {
            // 如果队列为空，直接返回
            if (_logQueue.IsEmpty)
                return;
                
            StringBuilder entriesBuilder = new StringBuilder();
            
            // 处理队列中的所有日志条目
            while (_logQueue.TryDequeue(out LogEntry entry))
            {
                string formattedMessage;
                
                if (entry.Exception != null)
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine(entry.Message);
                    sb.AppendLine($"异常类型: {entry.Exception.GetType().Name}");
                    sb.AppendLine($"异常消息: {entry.Exception.Message}");
                    sb.AppendLine($"堆栈跟踪: {entry.Exception.StackTrace}");

                    // 记录内部异常
                    Exception innerEx = entry.Exception.InnerException;
                    int innerExCount = 0;
                    while (innerEx != null && innerExCount < 5)
                    {
                        sb.AppendLine($"内部异常 {++innerExCount}:");
                        sb.AppendLine($"  类型: {innerEx.GetType().Name}");
                        sb.AppendLine($"  消息: {innerEx.Message}");
                        innerEx = innerEx.InnerException;
                    }
                    
                    formattedMessage = $"[{entry.Timestamp.ToString(Constants.DateTimeFormat)}] [{entry.Level}] {sb.ToString()}{Environment.NewLine}";
                }
                else
                {
                    formattedMessage = $"[{entry.Timestamp.ToString(Constants.DateTimeFormat)}] [{entry.Level}] {entry.Message}{Environment.NewLine}";
                }
                
                // 输出到调试窗口
                Debug.WriteLine(formattedMessage);
                
                // 添加到缓冲区
                lock (_lock)
                {
                    _logBuffer.Append(formattedMessage);
                }
            }
            
            // 如果缓冲区过大，立即刷新
            if (_logBuffer.Length > 8192)
            {
                FlushLogBuffer(null);
            }
        }

        private static void FlushLogBuffer(object state)
        {
            lock (_lock)
            {
                if (_logBuffer.Length == 0)
                    return;

                try
                {
                    // 检查日志文件大小是否超过上限
                    if (File.Exists(_logFilePath))
                    {
                        var fileInfo = new FileInfo(_logFilePath);
                        if (fileInfo.Length > MAX_LOG_FILE_SIZE)
                        {
                            // 创建新的日志文件
                            string newLogFileName = $"log_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.txt";
                            _logFilePath = Path.Combine(_logFolder, newLogFileName);
                        }
                    }
                    
                    // 使用异步方式写入文件以减少IO阻塞
                    using (var writer = new StreamWriter(_logFilePath, true, Encoding.UTF8, 8192))
                    {
                        writer.Write(_logBuffer.ToString());
                    }
                    
                    _logBuffer.Clear();
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"刷新日志缓冲区失败: {ex.Message}");
                }
            }
        }
        
        private static void CleanupOldLogs()
        {
            try
            {
                if (!Directory.Exists(_logFolder))
                    return;
                    
                var logFiles = Directory.GetFiles(_logFolder, "log_*.txt")
                    .Select(f => new FileInfo(f))
                    .OrderByDescending(f => f.LastWriteTime)
                    .ToList();
                    
                // 如果日志文件数量超过限制，删除最旧的文件
                if (logFiles.Count > MAX_LOG_FILES)
                {
                    foreach (var file in logFiles.Skip(MAX_LOG_FILES))
                    {
                        try
                        {
                            File.Delete(file.FullName);
                            Debug.WriteLine($"已删除旧日志文件: {file.Name}");
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine($"删除旧日志文件失败: {file.Name}, 错误: {ex.Message}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"清理旧日志文件失败: {ex.Message}");
            }
        }

        public static void Log(string message, LogLevel level = LogLevel.Info)
        {
            if (level < _minimumLogLevel)
                return;

            if (!_isInitialized)
                Initialize();

            // 将日志条目添加到队列
            _logQueue.Enqueue(new LogEntry 
            { 
                Message = message, 
                Level = level,
                Timestamp = DateTime.Now,
                Exception = null
            });
        }

        public static void LogError(string message, Exception ex)
        {
            if (LogLevel.Error < _minimumLogLevel)
                return;
                
            if (!_isInitialized)
                Initialize();
                
            // 将错误日志条目添加到队列
            _logQueue.Enqueue(new LogEntry 
            { 
                Message = message, 
                Level = LogLevel.Error,
                Timestamp = DateTime.Now,
                Exception = ex
            });
        }

        public static void Shutdown()
        {
            try
            {
                // 取消日志处理任务
                _logCancellation.Cancel();
                
                // 等待日志处理任务完成
                if (_logProcessingTask != null && !_logProcessingTask.IsCompleted)
                {
                    _logProcessingTask.Wait(1000); // 最多等待1秒
                }
                
                // 停止计时器
                _flushTimer?.Change(Timeout.Infinite, Timeout.Infinite);
                _flushTimer?.Dispose();

                // 处理队列中剩余的日志
                ProcessLogQueue();
                
                // 强制刷新所有日志
                FlushLogBuffer(null);

                // 记录应用程序关闭
                string shutdownMessage = $"[{DateTime.Now.ToString(Constants.DateTimeFormat)}] [Info] 应用程序关闭{Environment.NewLine}";
                
                // 直接写入文件而不是使用缓冲区
                File.AppendAllText(_logFilePath, shutdownMessage);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"关闭日志系统失败: {ex.Message}");
            }
        }
    }
}
